package com.googlecode.recycled.xml;

import com.googlecode.proxjed.Proxies;
import com.googlecode.proxjed.Proxy;
import com.googlecode.recycled.cache.ArgumentsToStringMethodCache;
import com.googlecode.recycled.lang.Cache;
import com.googlecode.recycled.lang.jse.lang.MethodNamePredicate;
import org.w3c.dom.Node;

import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import java.io.InputStream;

/**
 * @author Henryk Konsek
 */
public class XPathsBuilder {

    protected Cache<String, Object> evaluationCache;

    protected Cache<String, XPathExpression> compiledExpressionCache;

    protected NamespaceContext namespaceContext;

    public XPathsBuilder cacheEvaluation(Cache<String, Object> evaluationCache) {
        this.evaluationCache = evaluationCache;
        return this;
    }

    public XPathsBuilder cacheCompiledExpression(Cache<String, XPathExpression> compiledExpressionCache) {
        this.compiledExpressionCache = compiledExpressionCache;
        return this;
    }

    public XPathsBuilder namespaceContext(NamespaceContext namespaceContext) {
        this.namespaceContext = namespaceContext;
        return this;
    }

    protected XPaths configure(XPaths xPaths) {
        if (evaluationCache != null) {
            Proxy<XPath> proxy = new ArgumentsToStringMethodCache<XPath, Object>(xPaths.xpath, XPath.class, MethodNamePredicate.EQUAL("evaluate"), evaluationCache);
            xPaths.xpath = Proxies.proxy(proxy);
        }
        if (compiledExpressionCache != null) {
            xPaths.compiledExpressionCache = compiledExpressionCache;
        }
        if (namespaceContext != null) {
            xPaths.xpath.setNamespaceContext(namespaceContext);
        }
        return xPaths;
    }

    public XPaths build(Node node) {
        return configure(new XPaths(node));
    }

    public XPaths build(InputStream inputStream) {
        return configure(new XPaths(inputStream));
    }

}
